package com.huirui.server.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.huirui.server.constant.ProductStatusConstant;
import com.huirui.server.constant.ProductType;
import com.huirui.server.exception.SeckillActivityException;
import com.huirui.server.mapper.SeckillMapper;
import com.huirui.server.pojo.dto.SeckillDto;
import com.huirui.server.pojo.entity.Product;
import com.huirui.server.pojo.entity.ProductSpecification;
import com.huirui.server.pojo.entity.Seckill;
import com.huirui.server.pojo.result.PageResult;
import com.huirui.server.pojo.vo.SeckillProductVo;
import com.huirui.server.pojo.vo.SeckillVo;
import com.huirui.server.service.ProductService;
import com.huirui.server.service.ProductSpecificationService;
import com.huirui.server.service.SeckillService;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * @author yujun
 * @description 针对表【t_seckill(秒杀活动表)】的数据库操作Service实现
 * @createDate 2025-11-01 19:30:56
 */
@Service
public class SeckillServiceImpl extends ServiceImpl<SeckillMapper, Seckill>
        implements SeckillService {

    @Resource
    private ProductService productService;

    @Resource
    private ProductSpecificationService specificationService;


    @Override
    @Transactional
    public void addNewProduct(SeckillDto seckillDto) {
        // 已经是秒杀商品的话，不可以重新添加
        Product one = productService
                .lambdaQuery()
                .eq(Product::getId, seckillDto.getProductId())
                .select(Product::getProductType)
                .one();
        if (one == null) {
            throw new SeckillActivityException("商品不存在");
        }
        if (one.getProductType() == ProductType.SECKILL_PRODUCT) {
            throw new SeckillActivityException("秒杀商品不可以再次添加！");
        }
        productService
                .lambdaUpdate()
                .eq(Product::getId, seckillDto.getProductId())
                .set(Product::getProductType, ProductType.SECKILL_PRODUCT)
                .set(Product::getUpdateTime, LocalDateTime.now())
                .set(Product::getProductStatus, 0)
                .update();
        // 创建秒杀表
        Seckill seckill = new Seckill();
        seckill.setProductId(seckillDto.getProductId());
        seckill.setSeckillStatus(seckillDto.getStatus());
        seckill.setSeckillEndTime(seckillDto.getSeckillEndTime());
        seckill.setSeckillStartTime(seckillDto.getSeckillStartTime());
        seckill.setCreateTime(LocalDateTime.now());
        seckill.setUpdateTime(LocalDateTime.now());
        save(seckill);
        // 更新商品规格表
        List<ProductSpecification> specificationList = new ArrayList<>();
        seckillDto
                .getSeckillProductSpecificationDtoList()
                .forEach
                        (item -> {
                            ProductSpecification specification = new ProductSpecification();
                            specification.setId(item.getProductSpecificationId());
                            specification.setStock(Math.toIntExact(item.getStock()));
                            specification.setSeckillPrice(item.getSeckillPrice());
                            specification.setAvailableStock(Math.toIntExact(item.getStock()));
                            specification.setPromotionalPrice(item.getSeckillPrice());
                            specification.setUpdateTime(LocalDateTime.now());
                            specificationList.add(specification);
                        });
        specificationService.updateBatchById(specificationList);
    }

    @Override
    public PageResult<SeckillVo> listSeckillProduct(String productName, Long page, Long pageSize) {
        IPage<SeckillVo> ipage = new Page<>(page, pageSize);
        ipage = baseMapper.listSeckillProduct(productName, ipage);
        return PageResult.from(ipage);
    }

    @Override
    @Transactional
    public void deleteSeckillProduct(Long productId) {
        lambdaUpdate()
                .eq(Seckill::getProductId, productId)
                .remove();
        productService
                .lambdaUpdate()
                .eq(Product::getId, productId)
                .set(Product::getProductType, ProductType.GENERAL_PRODUCT)
                .set(Product::getProductStatus, ProductStatusConstant.OFF_SALE)
                .update();
    }

    @Override
    public void updateProduct(SeckillDto seckillDto) {
        lambdaUpdate()
                .eq(Seckill::getProductId, seckillDto.getProductId())
                .set(Seckill::getSeckillStatus, seckillDto.getStatus())
                .set(Seckill::getSeckillEndTime, seckillDto.getSeckillEndTime())
                .set(Seckill::getSeckillStartTime, seckillDto.getSeckillStartTime())
                .set(Seckill::getUpdateTime, LocalDateTime.now())
                .update();
        // 更新商品规格表
        List<ProductSpecification> specificationList = new ArrayList<>();
        seckillDto
                .getSeckillProductSpecificationDtoList()
                .forEach
                        (item -> {
                            ProductSpecification specification = new ProductSpecification();
                            specification.setId(item.getProductSpecificationId());
                            specification.setStock(Math.toIntExact(item.getStock()));
                            specification.setSeckillPrice(item.getSeckillPrice());
                            specification.setPromotionalPrice(item.getSeckillPrice());
                            specification.setAvailableStock(Math.toIntExact(item.getStock()));
                            specificationList.add(specification);
                        });
        specificationService.updateBatchById(specificationList);
    }

    @Override
    public PageResult<SeckillProductVo> listSeckillProduct(Integer type, Integer page, Integer pageSize) {
        IPage<Seckill> iPage = new Page<>(page, pageSize);
        // 首先查询出所有参与秒杀的商品ID
        if (type == 0) {
            // 查询正在秒杀的商品ID
            lambdaQuery()
                    .le(Seckill::getSeckillStartTime, LocalDateTime.now())
                    .ge(Seckill::getSeckillEndTime, LocalDateTime.now())
                    .eq(Seckill::getSeckillStatus, 0)
                    .select(Seckill::getProductId)
                    .page(iPage);
        } else if (type == 1) {
            // 查询即将秒杀的商品ID
            lambdaQuery()
                    .ge(Seckill::getSeckillStartTime, LocalDateTime.now())
                    .eq(Seckill::getSeckillStatus, 0)
                    .select(Seckill::getProductId)
                    .page(iPage);
        }
        List<Long> productIds = iPage.getRecords().stream().map(Seckill::getProductId).toList();
        List<SeckillProductVo> seckillProductVoList = productService.listSeckillProductInfoByProductIds(productIds);
        PageResult<SeckillProductVo> pageResult = new PageResult<>();
        pageResult.setCurrent(iPage.getCurrent());
        pageResult.setTotal(iPage.getTotal());
        pageResult.setSize(iPage.getSize());
        pageResult.setRecords(seckillProductVoList);
        pageResult.setPages(iPage.getPages());
        return pageResult;
    }

    @Override
    public SeckillVo getSeckillProductById(Long productId) {
        return baseMapper.getSeckillProductById(productId);
    }
}




